import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.exception.TransactionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;

/**
 * Created by xuguangyuansh on 2018/8/24.
 */
public class FabricConfig {

    private static Logger logger = LoggerFactory.getLogger(FabricConfig.class);

    /** 用户名 */
    private String user;
    /** 节点服务器对象 */
    private Peers peers;
    /** 排序服务器对象 */
    private Orderers orderers;
    /** 智能合约对象 */
    private Chaincode chaincode;
    /** channel-artifacts 所在路径：默认 channel-artifacts 所在路径/xxx/WEB-INF/classes/fabric/channel-artifacts/ */
    private String channelArtifactsPath;
    /** crypto-config 所在路径：默认 crypto-config 所在路径/xxx/WEB-INF/classes/fabric/crypto-config/ */
    private String cryptoConfigPath;
    private boolean registerEvent = false;

    public FabricConfig() {
        // 默认 channel-artifacts 所在路径 /xxx/WEB-INF/classes/fabric/channel-artifacts/
        channelArtifactsPath = getChannelPath() + "/channel-artifacts/";
        // 默认 crypto-config 所在路径 /xxx/WEB-INF/classes/fabric/crypto-config/
        cryptoConfigPath = getChannelPath() + "/crypto-config/";
    }

    public ChaincodeManager getChaincodeManager() throws IOException, NoSuchAlgorithmException, InvocationTargetException,
            InstantiationException, InvalidArgumentException, CryptoException, NoSuchProviderException, IllegalAccessException,
            NoSuchMethodException, InvalidKeySpecException, TransactionException, ClassNotFoundException {
        return new ChaincodeManager(user, this);
    }

    /**
     * 默认 Fabric 配置路径
     *
     * @return D:/installSoft/apache-tomcat-9.0.0/webapps/xxx/WEB-INF/classes/fabric/channel-artifacts/
     */
    private String getChannelPath() {
        logger.debug("classpath: " + FabricConfig.class.getClassLoader().getResource(""));
        String directorys = FabricConfig.class.getClassLoader().getResource("fabric").getFile();
        logger.debug("directorys = " + directorys);
        File directory = new File(directorys);
        logger.debug("directory = " + directory.getPath());

        return directory.getPath();
        // return "src/main/resources/fabric/channel-artifacts/";
    }

    public String getUser() {
        return user;
    }

    public FabricConfig setUser(String user) {
        this.user = user;
        return this;
    }

    public Peers getPeers() {
        return peers;
    }

    public FabricConfig setPeers(Peers peers) {
        this.peers = peers;
        return this;
    }

    public FabricConfig setPeers(String orgName, String orgMSPID, String orgDomainName) {
        this.peers = new Peers(orgName, orgMSPID, orgDomainName);
        return this;
    }

    /** 新增本地节点服务器 */
    public FabricConfig addPeer(String peerName, String peerEventHubName, String peerLocation,
                        String peerEventHubLocation, String caLocation) {
        peers.addPeer(peerName, peerEventHubName, peerLocation, peerEventHubLocation, caLocation);
        return this;
    }

    public Orderers getOrderers() {
        return orderers;
    }

    public FabricConfig setOrderers(Orderers orderers) {
        this.orderers = orderers;
        return this;
    }

    public FabricConfig setOrderers(String ordererDomainName) {
        this.orderers = new Orderers(ordererDomainName);
        return this;
    }

    public FabricConfig addOrderer(String name, String location) {
        orderers.addOrderer(name, location);
        return this;
    }

    public Chaincode getChaincode() {
        return chaincode;
    }

    public FabricConfig setChaincode(Chaincode chaincode) {
        this.chaincode = chaincode;
        return this;
    }

    public FabricConfig setChaincode(String channelName, String chaincodeName, String chaincodePath, String chaincodeVersion) {
        this.chaincode = new Chaincode(channelName, chaincodeName, chaincodePath, chaincodeVersion);
        return this;
    }

    public String getChannelArtifactsPath() {
        return channelArtifactsPath;
    }

    public FabricConfig setChannelArtifactsPath(String channelArtifactsPath) {
        this.channelArtifactsPath = channelArtifactsPath;
        return this;
    }

    public String getCryptoConfigPath() {
        return cryptoConfigPath;
    }

    public FabricConfig setCryptoConfigPath(String cryptoConfigPath) {
        this.cryptoConfigPath = cryptoConfigPath;
        return this;
    }

    public boolean isRegisterEvent() {
        return registerEvent;
    }

    public FabricConfig setRegisterEvent(boolean registerEvent) {
        this.registerEvent = registerEvent;
        return this;
    }


}
